﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;

namespace OmniKits.Windows.Behaviors
{
    public static class KeyGestureInput
    {
#pragma warning disable 1591

        private static readonly DependencyProperty KeyProperty = DependencyProperty.Register("Key", typeof(Key), typeof(KeyGestureInput));
        private static readonly DependencyProperty ModifiersProperty = DependencyProperty.Register("Modifiers", typeof(ModifierKeys), typeof(KeyGestureInput));

        internal static Key GetKey(this TextBox textbox)
        {
            return (Key)textbox.GetValue(KeyProperty);
        }
        internal static void SetKey(this TextBox textbox, Key value)
        {
            textbox.SetValue(KeyProperty, value);
        }
        internal static ModifierKeys GetModifiers(this TextBox textbox)
        {
            return (ModifierKeys)textbox.GetValue(ModifiersProperty);
        }
        internal static void SetModifiers(this TextBox textbox, ModifierKeys value)
        {
            textbox.SetValue(ModifiersProperty, value);
        }

        private static readonly RelaxKeyGestureConverter RelaxKeyGestureConverter = new RelaxKeyGestureConverter();
        private static readonly ModifierKeysConverter ModifierKeysConverter = new ModifierKeysConverter();

        public static ModifierKeys GetKeyboardModifiers()
        {
            var modifiers = Keyboard.Modifiers;
            if (Keyboard.IsKeyDown(Key.LWin) || Keyboard.IsKeyDown(Key.RWin))
                return modifiers | ModifierKeys.Windows;

            return modifiers;
        }

        public static ModifierKeys GetComputedModifiers(this TextBox textbox)
        {
            var modifiers = textbox.GetModifiers();

            if (modifiers == ModifierKeys.None)
                return textbox.GetForcedModifiers();

            return modifiers;
        }

        #region HoyKeyProperty

        private static void UpdateKey(this TextBox textbox)
        {
            textbox.SetKey(textbox.GetKeyGesture().Key);
        }
        private static readonly Regex FormatRegex = new Regex(@"\s*[+,]\s*");
        private static void UpdateKeyGestureText(this TextBox textbox)
        {
            var hk = GetKeyGesture(textbox) ?? new RelaxKeyGesture(Key.None);

            var mods = hk.Modifiers;
            var key = hk.Key;

            var text = RelaxKeyGestureConverter.ConvertToString(hk);

            if (key == 0 && mods != 0 && !textbox.GetAllowPureModifiers())
                text += " + ";

            textbox.Text = text;
            textbox.SelectionStart = text.Length;
        }
        public static readonly DependencyProperty KeyGestureProperty = DependencyProperty.RegisterAttached("KeyGesture", typeof(RelaxKeyGesture), typeof(KeyGestureInput),
            new PropertyMetadata
            {
                PropertyChangedCallback = (d, e) =>
                {
                    var textbox = d as TextBox;
                    if (textbox != null)
                    {
                        textbox.UpdateKey();
                        textbox.UpdateKeyGestureText();
                    }
                },
            });
        public static RelaxKeyGesture GetKeyGesture(this TextBox textbox)
        {
            return (RelaxKeyGesture)textbox.GetValue(KeyGestureProperty);
        }
        public static void SetKeyGesture(this TextBox textbox, RelaxKeyGesture hotkey)
        {
            textbox.SetValue(KeyGestureProperty, hotkey);
        }

        #endregion

        #region ForcedModifiersProperty

        internal static void UpdateKeyGesture(this TextBox textbox)
        {
            var hk = new RelaxKeyGesture(textbox.GetKey(), textbox.GetComputedModifiers());
            SetKeyGesture(textbox, hk);
        }
        public static readonly DependencyProperty ForcedModifiersProperty = DependencyProperty.RegisterAttached("ForcedModifiers", typeof(ModifierKeys), typeof(KeyGestureInput),
            new PropertyMetadata
            {
                PropertyChangedCallback = (d, e) =>
                {
                    var textbox = d as TextBox;
                    if (textbox != null)
                    {
                        textbox.UpdateKeyGesture();
                    }
                },
            });
        public static ModifierKeys GetForcedModifiers(this TextBox textbox)
        {
            return (ModifierKeys)textbox.GetValue(ForcedModifiersProperty);
        }
        public static void SetForcedModifiers(this TextBox textbox, ModifierKeys value)
        {
            textbox.SetValue(ForcedModifiersProperty, value);
        }

        #endregion

        #region AllowPureModifiersProperty

        public static readonly DependencyProperty AllowPureModifiersProperty = DependencyProperty.RegisterAttached("AllowPureModifiers", typeof(bool), typeof(KeyGestureInput),
            new PropertyMetadata
            {
                PropertyChangedCallback = (d, e) =>
                {
                    var textbox = d as TextBox;
                    if (textbox != null)
                    {
                        textbox.UpdateKeyGestureText();
                    }
                }
            });
        public static bool GetAllowPureModifiers(this TextBox textbox)
        {
            return (bool)textbox.GetValue(AllowPureModifiersProperty);
        }
        public static void SetAllowPureModifiers(this TextBox textbox, bool value)
        {
            textbox.SetValue(AllowPureModifiersProperty, value);
        }

        #endregion
    }
}
